/// Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Data;
using System.Text;
using System.Windows.Forms;
using Microsoft.VSPowerToys.PackInstallerDataModel;

namespace Microsoft.VSPowerToys.PackInstaller
{
	/// <summary>
	/// This is the control that houses the list of tools, as well as the header for an individual pack.
	/// </summary>
	public partial class PackListControl : UserControl
	{
        private List<ToolSummaryControl> shownControls;
        private List<ToolSummaryControl> hiddenControls;

#if TEST
        public PackItem CurrentPackData
        {
            get { return this.currentPackData; }
        }
#endif
        /// <summary>
        /// Reference to the pack data linked to this control
        /// </summary>
		private PackItem currentPackData;

        /// <summary>
		/// Constructor
		/// </summary>
		public PackListControl()
		{
			InitializeComponent();
			installPackCheckBox.Font = new Font(SystemFonts.DialogFont, FontStyle.Bold);
			packNameLinkLabel.Font = new Font(SystemFonts.DialogFont, FontStyle.Bold);
		}

		/// <summary>
		/// Accessor to retrieve the state of the Install Pack check box
		/// </summary>
		public CheckState PackCheckedState
		{
			get { return installPackCheckBox.CheckState; }
		}

		/// <summary>
		/// This method cascades the maintenance mode flag down to the individual tools in this pack.
		/// </summary>
		public void SetToolsMaintenanceMode(bool maintenanceModeEnabled)
		{
			ToolSummaryControl toolControl = null;
            bool toolEnabled = false;
            bool toolActive = false;
			for (int i = 0; i < toolsPanel.Controls.Count; i++)
			{
				toolControl = toolsPanel.Controls[i] as ToolSummaryControl;
				if (toolControl != null)
				{
					toolControl.MaintenanceModeEnabled = maintenanceModeEnabled;
					toolControl.InstallToolFlag = false;
					toolControl.RefreshInstallToolCheckBox();

                    toolEnabled |= toolControl.Enabled;
                    toolActive |= toolControl.Active;
					// Reset the reference so the next time through the loop we don't accidentally think
					// we have a tool when we don't.
					toolControl = null;
				}
			}

            // Enable the checkbox if one of the tools is active.
            this.installPackCheckBox.Enabled = toolActive;
			// We always uncheck the boxes when we flip the maintenance mode bit...
			this.installPackCheckBox.Checked = false;

            if (maintenanceModeEnabled)
            {
                // If no tools are showing then don't show this pack
                this.Visible = toolEnabled;
            }
            else
            {
                this.Visible = (toolsPanel.Controls.Count > 0);
            }
		}

        /// <summary>
        /// Filters the tools in the pack grup by the given parameter
        /// </summary>
        /// <param name="tag"></param>
        /// <param name="keyword"></param>
        /// <param name="searchVisibleOnly"></param>
        /// <returns>Returns the number of items being shown after this filtering</returns>
        public int FilterTools(string tag, string keyword, bool searchVisibleOnly)
        {
            bool toolListed = false;
            this.toolsPanel.SuspendLayout();
            System.Collections.IEnumerable controlList = searchVisibleOnly ?
                (System.Collections.IEnumerable)this.shownControls :
                (System.Collections.IEnumerable)toolsPanel.Controls;
            this.shownControls = new List<ToolSummaryControl>();
            foreach (ToolSummaryControl summaryControl in controlList)
            {
                ToolItem item = summaryControl.ToolData;
                if (item != null)
                {
                    bool filterResult = (String.IsNullOrEmpty(tag) || item.Tags.Contains(tag)) &&
                                        (String.IsNullOrEmpty(keyword) || item.ContainsText(keyword));
                    summaryControl.Visible = filterResult;
                    toolListed |= filterResult;
                    if (filterResult)
                    {
                        this.shownControls.Add(summaryControl);
                    }
                }
            }
            this.Visible = toolListed;
            this.toolsPanel.ResumeLayout(true);
            this.UpdatePartialSelectState();
            return this.shownControls.Count;
        }

		/// <summary>
		/// This method loads the GUI with the data for the pack.  Controls are dynamically created and added to the PackListControl
		/// </summary>
		/// <param name="packData"></param>
        public void LoadPackData(PackItem packData)
		{
        	if (packData != null)
			{
                this.shownControls = new List<ToolSummaryControl>();
                this.hiddenControls = new List<ToolSummaryControl>();

				this.currentPackData = packData;
				// We need to make sure we set the size of the control properly so the autoscroll on the parent container works right.
				this.Height = headerPanel.Height;

				if (packData.PackUrl == null)
				{
					installPackCheckBox.Text = packData.Name;
					packNameLinkLabel.Visible = false;
				}
				else
				{
					packNameLinkLabel.Text = packData.Name;
					packNameLinkLabel.Visible = true;
					// Setup a tooltip so that when the name link gets hovered over there are some instructions.
					toolTipProvider.SetToolTip(packNameLinkLabel, this.currentPackData.PackUrl.ToString());
				}
                this.SuspendLayout();
                toolsPanel.Controls.Clear();
                toolsPanel.Height = 15;
				ToolSummaryControl newToolControl = null;
                this.installPackCheckBox.Enabled = false;

                for (int i = 0; i < packData.Tools.Count; i++)
                {
                    if (!packData.Tools[i].HideThisTool)
                    {
                        newToolControl = packData.Tools[i].UserInterfaceControl as ToolSummaryControl;
                        if (newToolControl == null)
                        {
                            newToolControl = new ToolSummaryControl();
                            newToolControl.Name = packData.Tools[i].ToolName;
                            newToolControl.Tag = packData.Tools[i];
                            newToolControl.AutoSize = true;
                            newToolControl.AutoSizeMode = AutoSizeMode.GrowAndShrink;
                            newToolControl.Dock = DockStyle.Top;
                            newToolControl.TabIndex = i;
                            newToolControl.LoadToolData(packData.Tools[i]);
                            packData.Tools[i].UserInterfaceControl = newToolControl;
                        }
                        else
                        {
                            newToolControl.PerformAutoScale();
                        }
                        toolsPanel.Controls.Add(newToolControl);
                        if (newToolControl.Active)
                        {
                            this.installPackCheckBox.Enabled = true;
                        }
                        this.shownControls.Add(newToolControl);

                        newToolControl.BringToFront();
                    }
                }

                this.ResumeLayout(true);
			}
       	}

		/// <summary>
		/// This method overrides the painting for the control.  Here we draw the horizontal single pixel high gradient as a separator.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void PackListControl_Paint(object sender, PaintEventArgs e)
		{
			Rectangle horizontalRuleArea = new Rectangle(new Point(this.headerPanel.Left, this.headerPanel.Bottom - 1), new Size(this.headerPanel.Width, 1));
			if (horizontalRuleArea.Width > 0 && horizontalRuleArea.Height > 0)
			{
				LinearGradientBrush horizontalRuleBrush = new LinearGradientBrush(horizontalRuleArea, SystemColors.ControlDark, this.BackColor, 0.0f);
				e.Graphics.FillRectangle(horizontalRuleBrush, horizontalRuleArea);
			}
		}

		/// <summary>
		/// This method will rip through and determine what state the Install Pack check box should be in.
		/// </summary>
		public void UpdatePartialSelectState()
		{
            bool checkedSeen = false;
            bool uncheckedSeen = false;
			ToolSummaryControl currentTool = null;
			for (int i = 0; i < toolsPanel.Controls.Count; i++)
			{
				currentTool = toolsPanel.Controls[i] as ToolSummaryControl;
				if (currentTool != null && currentTool.Active && currentTool.Visible) 
				{
                    if (currentTool.InstallToolFlag == true)
                    {
                        checkedSeen = true;
                    }
                    else
                    {
                        uncheckedSeen = true;
                    }
				}
			}

            if (!checkedSeen)
            {
                installPackCheckBox.Checked = false;
            }
            else
            {
                installPackCheckBox.CheckState = uncheckedSeen ? CheckState.Indeterminate : CheckState.Checked;
            }
			
			PackInstallerForm pif = this.ParentForm as PackInstallerForm;
			if (pif != null)
			{
				pif.UpdateInstallButton(installPackCheckBox.Checked);
			}
		}

		/// <summary>
		/// This is the click event handler for the Install Pack check box.  We go through each tool and either check it or uncheck it
		/// based on the state of the pack check box.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void _InstallPackCheckBox_Click(object sender, EventArgs e)
		{
			ToolSummaryControl currentTool = null;
			for (int i = 0; i < toolsPanel.Controls.Count; i++)
			{
				currentTool = toolsPanel.Controls[i] as ToolSummaryControl;
				if (currentTool != null && currentTool.Visible)
				{
					currentTool.InstallToolFlag = installPackCheckBox.Checked;
				}
			}

			PackInstallerForm pif = this.ParentForm as PackInstallerForm;
			if (pif != null)
			{
				pif.UpdateInstallButton(installPackCheckBox.Checked);
			}
		}

		/// <summary>
		/// This is the event handler for the user clicking on the link label of the Pack's name.
		/// We launch the URL as a process, this lets the system registered browser display the page.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		private void packNameLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
		{
			System.Diagnostics.Process.Start(this.currentPackData.PackUrl.ToString());
		}

        /// <summary>
        /// This method will resize the tools for this pack to be the appropriate size.
        /// </summary>
        public void SizePackAndTools()
        {
            if (this.toolsPanel.Controls.Count > 0)
            {
                ToolSummaryControl currentTool = null;
                foreach (Control toolControl in this.toolsPanel.Controls)
                {
                    currentTool = toolControl as ToolSummaryControl;
                    if (currentTool != null)
                    {
                        currentTool.SizeToContent();
                    }
                }
            }
        }
	}
}
